//! # My mod Crate
//!
//! `my_mod_crate` is a collection of utilities to make performing certain
//! calculations more convenient.

/// Adds one to the number given.
// --snip--

pub mod mymod1;

pub mod mymod2;

pub mod print_format_mod;

pub mod compound_type_test;

pub mod tuples;

pub mod literals_and_operators;

pub mod arrays_and_slices;

pub mod mod_enum_test;

pub mod mod_enum_test2;

pub mod clike_test;

pub mod structuresx;

pub mod testcase_linked_list_test;

pub mod constants_test;

pub mod variable_bindings_test;

pub mod mutability_test;

pub mod scope_and_shadowing_test;

pub mod declare_first_test;

pub mod casting_test;

pub mod literals_test;

pub mod inference_test;

pub mod aliasing_test;

pub mod conversion_from_and_into_test;

pub mod to_and_from_strings;

pub mod expressions_test;

pub mod flow_control_test;

pub mod match_test;
pub mod tuples_test2;
pub mod enums_test2;
pub mod pointers_ref_test;
pub mod structs_test2;
pub mod guards_test;
pub mod binding_test;
pub mod if_let_test;
pub mod while_let_test;
pub mod functions_test;
pub mod methods_test;
pub mod closures_test;
pub mod capturing_test;
pub mod as_input_parameters_test;
pub mod type_anonymity_test;
pub mod input_functions_test;
pub mod as_output_parameters_test;
pub mod iterator_any_test;
pub mod iterator_find_test;
pub mod higher_order_functions_test;
pub mod diverging_functions_test;
pub mod base64code;
pub mod cfg_test;
pub mod rust_index;
pub mod generic_test01;
pub mod functions_test2;
pub mod implementation_test;
pub mod traits_test2;
pub mod bounds_test;
pub mod testcase_empty_bounds_test;
pub mod multiple_bounds_test;
pub mod where_clauses_test;
pub mod new_type_idiom_test;
pub mod the_problem_test;
pub mod associated_types_test;
pub mod phantom_type_parameters_test;
pub mod testcase_unit_clarification_test;
pub mod raii_test;
pub mod ownership_and_moves_test;
pub mod mutability_test2;
pub mod borrowing_test;
pub mod mutability_test3;
pub mod freezing_test;
pub mod aliasing_test2;
pub mod the_ref_pattern;
pub mod joseph2;
pub mod lifetimes_test;
pub mod lifetimes_explicit_annotation_test;
pub mod lifetimes_functions;
pub mod lifetimes_methods;
pub mod lifetimes_structs;
pub mod lifetimes_bounds;
pub mod lifetimes_coercion;
pub mod lifetimes_static;
pub mod lifetimes_elision;
pub mod traits_test3;
pub mod traits_test3_derive;
pub mod traits_test3_operator_overloading;
pub mod traits_test3_drop;
pub mod traits_test3_iterators;
pub mod traits_test3_clone;
pub mod macro_rules;
pub mod macro_rules_designators;
pub mod macro_rules_overload;
// pub mod producers_consumers;
pub mod macro_rules_repeat;
pub mod macro_rules_dry;
pub mod domain_specific_languages_dsls;
pub mod variadic_interfaces;
pub mod unicode_utf8;
pub mod panic_test;
pub mod option_unwrap;
pub mod option_result_test;
pub mod combinator_map;
pub mod combinator_and_then;
pub mod use_box_process_err;
pub mod result_struct;
pub mod result_struct_map;
pub mod result_struct_alias;
pub mod result_many_err_type;
pub mod result_early_return;
pub mod try_macro;
pub mod make_new_err_type;
pub mod try_macro_other_use;
pub mod use_box_process_error;
pub mod std_box_stack;
pub mod strd_vector;
pub mod std_string;
pub mod std_option;
pub mod std_result;
pub mod question_mark_operator;
pub mod std_hash_map;
pub mod change_custom_key_type;
pub mod std_hash_set;
pub mod std_thread;
pub mod std_channel;
pub mod std_path;
pub mod std_file_io;
pub mod std_sub_process;
pub mod std_command_channel;
pub mod std_command_wait;
pub mod std_file_system;
pub mod std_program_args;
pub mod std_other_lang_func_interface;
pub mod macro_rules_2;
pub mod wl_lib;
pub mod tcpudp;
pub mod proc_macro01;
pub mod proc_macro02;
pub mod regex_text;


#[macro_export]
macro_rules! strfrm {
    ( $( $x:expr ),* ) => {
        {
            let mut temp_str = String::from("");
            $(
                temp_str.push_str($x);
                temp_str.push(' ');
            )*
            temp_str
        }
    };
}

pub trait HM {
    fn h_macro() -> String {
        String::from("T_T")
    }
}


pub mod my_mod {
    // Items in modules default to private visibility.
    fn private_function() {
        println!("called `my_mod::private_function()`");
    }

    // Use the `pub` modifier to override default visibility.
    pub fn function() {
        println!("called `my_mod::function()`");
    }

    // Items can access other items in the same module,
    // even when private.
    pub fn indirect_access() {
        print!("called `my_mod::indirect_access()`, that\n> ");
        private_function();
    }

    // Modules can also be nested
    pub mod nested {
        pub fn function() {
            println!("called `my_mod::nested::function()`");
        }

        #[allow(dead_code)]
        fn private_function() {
            println!("called `my_mod::nested::private_function()`");
        }

        // Functions declared using `pub(in path)` syntax are only visible
        // within the given path. `path` must be a parent or ancestor module
        pub(in my_mod) fn public_function_in_my_mod() {
            print!("called `my_mod::nested::public_function_in_my_mod()`, that\n > ");
            public_function_in_nested()
        }

        // Functions declared using `pub(self)` syntax are only visible within
        // the current module
        pub(self) fn public_function_in_nested() {
            println!("called `my_mod::nested::public_function_in_nested");
        }

        // Functions declared using `pub(super)` syntax are only visible within
        // the parent module
        pub(super) fn public_function_in_super_mod() {
            println!("called my_mod::nested::public_function_in_super_mod");
        }
    }

    pub fn call_public_function_in_my_mod() {
        print!("called `my_mod::call_public_funcion_in_my_mod()`, that\n> ");
        nested::public_function_in_my_mod();
        print!("> ");
        nested::public_function_in_super_mod();
    }

    // pub(crate) makes functions visible only within the current crate
    pub(crate) fn public_function_in_crate() {
        println!("called `my_mod::public_function_in_crate()");
    }

    // Nested modules follow the same rules for visibility
    mod private_nested {
        #[allow(dead_code)]
        pub fn function() {
            println!("called `my_mod::private_nested::function()`");
        }
    }
}

pub fn function() {
    println!("called `function()`");
}

pub fn my_mod_test() {
    // Modules allow disambiguation between items that have the same name.
    function();
    my_mod::function();

    // Public items, including those inside nested modules, can be
    // accessed from outside the parent module.
    my_mod::indirect_access();
    my_mod::nested::function();
    my_mod::call_public_function_in_my_mod();

    // pub(crate) items can be called from anywhere in the same crate
    my_mod::public_function_in_crate();

    // pub(in path) items can only be called from within the mode specified
    // Error! function `public_function_in_my_mod` is private
    //my_mod::nested::public_function_in_my_mod();
    // TODO ^ Try uncommenting this line

    // Private items of a module cannot be directly accessed, even if
    // nested in a public module:

    // Error! `private_function` is private
    //my_mod::private_function();
    // TODO ^ Try uncommenting this line

    // Error! `private_function` is private
    //my_mod::nested::private_function();
    // TODO ^ Try uncommenting this line

    // Error! `private_nested` is a private module
    //my_mod::private_nested::function();
    // TODO ^ Try uncommenting this line
}


#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
        assert_eq!(2 + 2, 4);
    }
}
